#include <socklibpp/sockstream.h>
#include "SiteProcessorTask.h"
#include "DiffHLEngine.h"
#include "EmailManager.h"
#include "ConfigValues.h"
#include "Utils.h"
#include "Defines.h"
#include "Protocol.h"
#include "LogManager.h"
#include <process.h>
#include <list>

using namespace socklib;

#define RECEIVE_BUFFER_SIZE 1024*1024

void ProcessDiff(const PPACKET packet, const unsigned int& length, base* client)
{
    if (packet->header.subtype != PACKET_SUBTYPE_REQUEST)
    {
        LOGT(("ProcessDiff. Invalid packet subtype\n"));
        return;
    }
    if (length != sizeof(packet->header) + sizeof(packet->data.packetDataRequestDiff))
    {
        LOGT(("ProcessDiff. Invalid packet length\n"));
        return;
    }
    LOGT(("ProcessDiff. MonitorID: %u. ResourceID: %u. ResourceID: %u. HL font color: 0x%08X, HL bk color: 0x%08X, HL font style: 0x%08X. DHL type: %u\n",
            packet->data.packetDataRequestDiff.monitor_id,
            packet->data.packetDataRequestDiff.resource1_id,
            packet->data.packetDataRequestDiff.resource2_id,
            packet->data.packetDataRequestDiff.highlight_font_color,
            packet->data.packetDataRequestDiff.highlight_bk_color,
            packet->data.packetDataRequestDiff.highlight_font_style,
            packet->data.packetDataRequestDiff.dhl_type));

    if (packet->data.packetDataRequestDiff.dhl_type != DHL_TYPE_ALL_PAGE &&
        packet->data.packetDataRequestDiff.dhl_type != DHL_TYPE_ONLY_CHANGES_SUMMARY)
    {
        LOGT(("ProcessDiff. Invalid DHL type\n"));
        return;
    }

    PACKET answer;
    answer.header.type = PACKET_TYPE_DIFF;
    answer.header.subtype = PACKET_SUBTYPE_ANSWER;
    answer.data.packetDataAnswerDiff.operation_status = OPERATION_STATUS_SUCCESSFUL;
    answer.data.packetDataAnswerDiff.diff_result_length = sizeof(packet->data.packetDataAnswerDiff);
    answer.data.packetDataAnswerDiff.triggers_count = 0;
    answer.data.packetDataAnswerDiff.diff_result[0] = 0;

    string szXPath;
    unsigned int uiTriggerType; 
    string szTriggerParams;
    string szUserCharset;
    unsigned int uiRealResourceID1 = 0;
    unsigned int uiRealResourceID2 = 0;
    string szResource1;
    string szResource2;
    string szResponseHeader1;
    string szResponseHeader2;    
    string szEffectiveUrl1;
    string szEffectiveUrl2;
    if (dbLayer->GetMonitorTriggerInfo( packet->data.packetDataRequestDiff.monitor_id,
                                        szXPath, uiTriggerType, szTriggerParams, szUserCharset) &&
        dbLayer->GetDownloadedResource(packet->data.packetDataRequestDiff.monitor_id,
                                       packet->data.packetDataRequestDiff.resource1_id,
                                       uiRealResourceID1, szResource1, szResponseHeader1, szEffectiveUrl1) &&
        dbLayer->GetDownloadedResource(packet->data.packetDataRequestDiff.monitor_id,
                                       packet->data.packetDataRequestDiff.resource2_id,
                                       uiRealResourceID2, szResource2, szResponseHeader2, szEffectiveUrl2))
    {
        bool bDiffCacheInput = false;
        bool bDiffCacheOutput = false;
        unsigned int uiQtyTriggers = 0;
        unsigned int uiQtyAnchors = 0;
        double dDiffTotalTime = 0;
        string szDiffCache;
        string szDiffHLResult;
        xmlDocPtr pDiffHLResult = NULL;
        xmlDocPtr pChangesSummary = NULL;
        unsigned int uiBlocksAdded = 0;
        unsigned int uiBlocksDeleted = 0;

        string szCharset1;
        string szCharset2;
        string szContentType1;
        string szContentType2;
        unsigned int uiContentType1 = CONTENT_TYPE_UNKNOWN; 
        unsigned int uiContentType2 = CONTENT_TYPE_UNKNOWN;
        
        GetContentCharsetFromResponse(szResponseHeader1, szCharset1);
        GetContentCharsetFromResponse(szResponseHeader2, szCharset2);
        GetContentTypeFromResponse(szResponseHeader1, szContentType1, uiContentType1);
        GetContentTypeFromResponse(szResponseHeader2, szContentType2, uiContentType2);

        DiffHLEngine dhlEngine;
        dhlEngine.SetPreviousResource(szResource1, szUserCharset, szCharset1, szEffectiveUrl1, uiContentType1);
        dhlEngine.SetCurrentResource(szResource2, szUserCharset, szCharset2, szEffectiveUrl2, uiContentType2);

        if (uiRealResourceID1 && uiRealResourceID2 &&
            dbLayer->GetDiffCache(uiRealResourceID1, uiRealResourceID2, szDiffCache, bDiffCacheInput) &&
            bDiffCacheInput)
        {
            LOGT(("ProcessDiff. Diff cache finded\n"));
        }

        dhlEngine.Process(  packet->data.packetDataRequestDiff.highlight_font_color,
                            packet->data.packetDataRequestDiff.highlight_bk_color,
                            packet->data.packetDataRequestDiff.highlight_font_style,
                            szXPath, uiTriggerType, szTriggerParams,
                            bDiffCacheInput, bDiffCacheOutput, szDiffCache, dDiffTotalTime,
                            pDiffHLResult, pChangesSummary,                            
                            uiBlocksAdded, uiBlocksDeleted,
                            uiQtyTriggers, uiQtyAnchors);
        LOGT(("ProcessDiff. DHL process completed. Triggers qty: %u. Anchors qty: %u\n", uiQtyTriggers, uiQtyAnchors));

        if (packet->data.packetDataRequestDiff.dhl_type == DHL_TYPE_ALL_PAGE)
            dhlEngine.DumpDiffHLResult(pDiffHLResult, szDiffHLResult);
        if (packet->data.packetDataRequestDiff.dhl_type == DHL_TYPE_ONLY_CHANGES_SUMMARY)
            dhlEngine.DumpChangesSummary(pChangesSummary,
                                        packet->data.packetDataRequestDiff.highlight_font_color,
                                        packet->data.packetDataRequestDiff.highlight_bk_color,
                                        packet->data.packetDataRequestDiff.highlight_font_style,
                                        uiTriggerType, szTriggerParams, szDiffHLResult);
        unsigned int uiResultSize = szDiffHLResult.size();
        if (uiResultSize)
        {
            unsigned int uiAnswerSize = sizeof(packet->header) + sizeof(packet->data.packetDataAnswerDiff) + uiResultSize;
            void* buffer = malloc(uiAnswerSize);
            PPACKET answer = (PPACKET)buffer;
            answer->header.type = PACKET_TYPE_DIFF;
            answer->header.subtype = PACKET_SUBTYPE_ANSWER;
            answer->data.packetDataAnswerDiff.operation_status = OPERATION_STATUS_SUCCESSFUL;
            answer->data.packetDataAnswerDiff.diff_result_length = uiResultSize+sizeof(packet->data.packetDataAnswerDiff.diff_result);
            answer->data.packetDataAnswerDiff.triggers_count = uiQtyTriggers;
            strcpy(answer->data.packetDataAnswerDiff.diff_result, szDiffHLResult.c_str());
            LOGT(("ProcessDiff. OperationStatus: 0x%08X\n", answer->data.packetDataAnswerDiff.operation_status));
            client->send((const char*)answer, uiAnswerSize);
            free(buffer);
            if (bDiffCacheOutput && uiRealResourceID1 && uiRealResourceID2)
            {
                LOGT(("ProcessDiff. Diff time: %.6f\n", dDiffTotalTime));
                if (dbLayer->SaveDiffCache(uiRealResourceID1, uiRealResourceID2, szDiffCache, dDiffTotalTime, DiffHLEngine::GetVersion()))
                    LOGT(("ProcessDiff. Save diff cache for %u and %u completed\n", uiRealResourceID1, uiRealResourceID2));
            }
            return;
        }
    }
    else
    {
        answer.data.packetDataAnswerDiff.operation_status = OPERATION_STATUS_DB_ERROR;
    }
    LOGT(("ProcessDiff. OperationStatus: 0x%08X\n", answer.data.packetDataAnswerDiff.operation_status));
    client->send((const char*)&answer, sizeof(answer.header) + sizeof(answer.data.packetDataAnswerDiff));
}

void ProcessCreateEmail(const PPACKET packet, const unsigned int& length, base* client)
{
    if (packet->header.subtype != PACKET_SUBTYPE_REQUEST)
    {
        LOGT(("ProcessCreateEmail. Invalid packet subtype\n"));
        return;
    }
    if (length != sizeof(packet->header)+packet->data.packetDataRequestCreateEmail.total_size)
    {
        LOGT(("ProcessCreateEmail. Invalid packet length\n"));
        return;
    }
    LOGT(("ProcessCreateEmail. AccountID: %u. MonitorID: %u. \n",
            packet->data.packetDataRequestCreateEmail.account_id,
            packet->data.packetDataRequestCreateEmail.monitor_id));

    PACKET answer;
    answer.header.type = PACKET_TYPE_CREATE_EMAIL;
    answer.header.subtype = PACKET_SUBTYPE_ANSWER;
    answer.data.packetDataAnswerCreateEmail.operation_status = OPERATION_STATUS_SUCCESSFUL;

    const char* offset = (const char*)packet+sizeof(packet->header);
    offset += sizeof(packet->data.packetDataRequestCreateEmail.total_size);
    offset += sizeof(packet->data.packetDataRequestCreateEmail.account_id);
    offset += sizeof(packet->data.packetDataRequestCreateEmail.monitor_id);
    offset += sizeof(packet->data.packetDataRequestCreateEmail.email_content_type);
    offset += sizeof(packet->data.packetDataRequestCreateEmail.alert_at_time);
    unsigned int uiAccountID = packet->data.packetDataRequestCreateEmail.account_id;
    unsigned int uiMonitorID = packet->data.packetDataRequestCreateEmail.monitor_id;
    unsigned char ucEmailContentType =  packet->data.packetDataRequestCreateEmail.email_content_type;
    int iAlertAtTime = packet->data.packetDataRequestCreateEmail.alert_at_time;
    if (*((unsigned int*)offset) > length-((unsigned int)offset-(unsigned int)packet)+sizeof(packet->data.packetDataRequestCreateEmail.email_from_length))
    {
        LOGT(("ProcessCreateEmail. Invalid length of packet field 'email_from_length'\n"));
        return;
    }
    string szEmailFrom = string(offset+sizeof(packet->data.packetDataRequestCreateEmail.email_from_length), *((unsigned int*)offset)-1);    
    offset += *((unsigned int*)offset) + sizeof(packet->data.packetDataRequestCreateEmail.email_from_length);
    if (*((unsigned int*)offset) > length-((unsigned int)offset-(unsigned int)packet)+sizeof(packet->data.packetDataRequestCreateEmail.email_to_length))
    {
        LOGT(("ProcessCreateEmail. Invalid length of packet field 'email_to_length'\n"));
        return;
    }
    string szEmailTo = string(offset+sizeof(packet->data.packetDataRequestCreateEmail.email_to_length), *((unsigned int*)offset)-1);
    offset += *((unsigned int*)offset) + sizeof(packet->data.packetDataRequestCreateEmail.email_to_length);
    if (*((unsigned int*)offset) > length-((unsigned int)offset-(unsigned int)packet)+sizeof(packet->data.packetDataRequestCreateEmail.email_cc_length))
    {
        LOGT(("ProcessCreateEmail. Invalid length of packet field 'email_cc_length'\n"));
        return;
    }
    string szEmailCc = string(offset+sizeof(packet->data.packetDataRequestCreateEmail.email_cc_length), *((unsigned int*)offset)-1);
    offset += *((unsigned int*)offset) + sizeof(packet->data.packetDataRequestCreateEmail.email_cc_length);
    if (*((unsigned int*)offset) > length-((unsigned int)offset-(unsigned int)packet)+sizeof(packet->data.packetDataRequestCreateEmail.email_bcc_length))
    {
        LOGT(("ProcessCreateEmail. Invalid length of packet field 'email_bcc_length'\n"));
        return;
    }
    string szEmailBcc = string(offset+sizeof(packet->data.packetDataRequestCreateEmail.email_bcc_length), *((unsigned int*)offset)-1);
    offset += *((unsigned int*)offset) + sizeof(packet->data.packetDataRequestCreateEmail.email_bcc_length);
    if (*((unsigned int*)offset) > length-((unsigned int)offset-(unsigned int)packet)+sizeof(packet->data.packetDataRequestCreateEmail.variables_length))
    {
        LOGT(("ProcessCreateEmail. Invalid length of packet field 'variables_length'\n"));
        return;
    }
    const char* szVariables = offset+sizeof(packet->data.packetDataRequestCreateEmail.variables_length);
    unsigned int uiVariablesSize = *((unsigned int*)offset)-1;
    offset += *((unsigned int*)offset) + sizeof(packet->data.packetDataRequestCreateEmail.variables_length);    
    if (*((unsigned int*)offset) > length-((unsigned int)offset-(unsigned int)packet)+sizeof(packet->data.packetDataRequestCreateEmail.email_template_name_length))
    {
        LOGT(("ProcessCreateEmail. Invalid length of packet field 'email_template_name_length'\n"));
        return;
    }
    string szEmailTemplateName = string(offset+sizeof(packet->data.packetDataRequestCreateEmail.email_template_name_length), *((unsigned int*)offset)-1);
    offset += *((unsigned int*)offset) + sizeof(packet->data.packetDataRequestCreateEmail.email_template_name_length);
    if (*((unsigned int*)offset) > length-((unsigned int)offset-(unsigned int)packet)+sizeof(packet->data.packetDataRequestCreateEmail.email_subject_length))
    {
        LOGT(("ProcessCreateEmail. Invalid length of packet field 'email_subject_length'\n"));
        return;
    }
    string szEmailSubject = string(offset+sizeof(packet->data.packetDataRequestCreateEmail.email_subject_length), *((unsigned int*)offset)-1);
    offset += *((unsigned int*)offset) + sizeof(packet->data.packetDataRequestCreateEmail.email_subject_length);    
    if (*((unsigned int*)offset) > length-((unsigned int)offset-(unsigned int)packet)+sizeof(packet->data.packetDataRequestCreateEmail.email_template_length))
    {
        LOGT(("ProcessCreateEmail. Invalid length of packet field 'email_template_length'\n"));
        return;
    }
    string szEmailTemplate = string(offset+sizeof(packet->data.packetDataRequestCreateEmail.email_template_length), *((unsigned int*)offset)-1);
    offset += *((unsigned int*)offset) + sizeof(packet->data.packetDataRequestCreateEmail.email_template_length);

    VariablesMap variables;
    vector<string> words;
    vector<string>::iterator iter;
    StringToWords(string(szVariables, uiVariablesSize), '\0', words);
    bool bIsVariable = true;
    iter = words.begin();
    while (true)
    {
        string szParam;
        string szValue;
        if (iter != words.end())
            szParam = *iter;
        else
            break;
        iter++;
        if (iter != words.end())
            szValue = *iter;
        else
            break;
        iter++;
        variables.insert(VariablesMapPair(szParam, szValue));
    }

    EmailManager emailManager;    
    string szEmailBody;
    string szEmailSender;
    vector<string> recipients;
    if (emailManager.CreateEmailOnDemand(   uiMonitorID, uiAccountID,
                                            ucEmailContentType, szEmailFrom, szEmailTo, szEmailCc, szEmailBcc,
                                            variables, szEmailTemplateName,
                                            szEmailSubject, szEmailTemplate,
                                            szEmailBody, szEmailSender, recipients))
    {
        LOGT(("ProcessCreateEmail. Create email content completed\n"));
        if (dbLayer->SaveEmailToStorage(uiMonitorID, uiAccountID, szEmailSender, recipients, iAlertAtTime, 0, szEmailBody, config_db_compress_emails))
            LOGT(("ProcessCreateEmail. Save email content to DB completed\n"));
        else
            answer.data.packetDataAnswerCreateEmail.operation_status = OPERATION_STATUS_DB_ERROR;
    }
    else
    {
        answer.data.packetDataAnswerCreateEmail.operation_status = OPERATION_STATUS_EMAIL_CREATION_ERROR;
    }

    LOGT(("ProcessCreateEmail. OperationStatus: 0x%08X\n", answer.data.packetDataAnswerCreateEmail.operation_status));
    client->send((const char*)&answer, sizeof(answer.header) + sizeof(answer.data.packetDataAnswerCreateEmail));
}

void ProcessCreateFeed(const PPACKET packet, const unsigned int& length, base* client)
{
    if (packet->header.subtype != PACKET_SUBTYPE_REQUEST)
    {
        LOGT(("ProcessCreateFeed. Invalid packet subtype\n"));
        return;
    }
    if (length != sizeof(packet->header)+sizeof(packet->data.packetDataRequestCreateFeed))
    {
        LOGT(("ProcessCreateFeed. Invalid packet length\n"));
        return;
    }
    LOGT(("ProcessCreateFeed. MonitorID: %u. Feed type: %u\n",
        packet->data.packetDataRequestCreateFeed.monitor_id,
        packet->data.packetDataRequestCreateFeed.feed_type));    

    if (packet->data.packetDataRequestCreateFeed.feed_type != FEED_TYPE_RSS &&
        packet->data.packetDataRequestCreateFeed.feed_type != FEED_TYPE_ATOM)
    {
        LOGT(("ProcessCreateFeed. Invalid feed type\n"));
        return;
    }

    PACKET answer;
    answer.header.type = PACKET_TYPE_CREATE_EMAIL;
    answer.header.subtype = PACKET_SUBTYPE_ANSWER;
    answer.data.packetDataAnswerCreateFeed.operation_status = OPERATION_STATUS_SUCCESSFUL;

    string szUrl;
    string szTitle;
    unsigned int uiMonitorID = packet->data.packetDataRequestCreateFeed.monitor_id;
    if (dbLayer->GetMonitorTitleInfo(uiMonitorID, szUrl, szTitle))
    {
        DiffHLEngine dhlEngine;
        switch (packet->data.packetDataRequestCreateFeed.feed_type)
        {
        case FEED_TYPE_RSS:
            {
                string szRssFeed;
                dhlEngine.CreateRssFeed(szRssFeed, "rss_first_item_template.xml", szTitle, szUrl, uiMonitorID, 0, 0, "");
                if (szRssFeed.size())
                {
                    if (dbLayer->SaveFeed(uiMonitorID, CONTENT_TYPE_XML | CONTENT_TYPE_RSS, szRssFeed))
                    {
                        LOGT(("ProcessCreateFeed. Save RSS feed to DB completed\n"));
                    }
                    else
                    {
                        answer.data.packetDataAnswerCreateFeed.operation_status = OPERATION_STATUS_FEED_CREATION_ERROR;
                    }
                }
                else
                {
                    answer.data.packetDataAnswerCreateFeed.operation_status = OPERATION_STATUS_FEED_CREATION_ERROR;
                }
                break;
            }
        case FEED_TYPE_ATOM:
            {
                string szAtomFeed;
                dhlEngine.CreateAtomFeed(szAtomFeed, "atom_first_item_template.xml", szTitle, szUrl, uiMonitorID, 0, 0, "");
                if (szAtomFeed.size())
                {
                    if (dbLayer->SaveFeed(uiMonitorID, CONTENT_TYPE_XML | CONTENT_TYPE_ATOM, szAtomFeed))
                    {
                        LOGT(("ProcessCreateFeed. Save Atom feed to DB completed\n"));
                    }
                    else
                    {
                        answer.data.packetDataAnswerCreateFeed.operation_status = OPERATION_STATUS_FEED_CREATION_ERROR;
                    }
                }
                else
                {
                    answer.data.packetDataAnswerCreateFeed.operation_status = OPERATION_STATUS_FEED_CREATION_ERROR;
                }
                break;
            }
        }
    }
    else
    {
        answer.data.packetDataAnswerCreateFeed.operation_status = OPERATION_STATUS_FEED_CREATION_ERROR;
    }    

    LOGT(("ProcessCreateFeed. OperationStatus: 0x%08X\n", answer.data.packetDataAnswerCreateFeed.operation_status));
    client->send((const char*)&answer, sizeof(answer.header) + sizeof(answer.data.packetDataAnswerCreateFeed));
}

void ProcessPacket(const char* buffer, unsigned int length, base* client)
{
    PPACKET packet = (PPACKET)buffer;
    LOGT(("ProcessPacket. PacketType: %u, PacketSubType: %u\n", packet->header.type, packet->header.subtype));
    switch (packet->header.type)
    {
    case PACKET_TYPE_DIFF:
        {
            ProcessDiff(packet, length, client);
            break;
        }
    case PACKET_TYPE_CREATE_EMAIL:
        {
            ProcessCreateEmail(packet, length, client);
            break;
        }
    case PACKET_TYPE_CREATE_FEED:
        {
            ProcessCreateFeed(packet, length, client);
            break;
        }
    default:
        {
            LOGT(("ProcessPacket. Invalid packet type\n"));
        }
    }
}

unsigned __stdcall ConnectionThreadProc(LPVOID lpParameter)
{
    base* client = (base*)lpParameter;
    char* buffer = (char*)malloc(RECEIVE_BUFFER_SIZE);
    memset(buffer, 0, RECEIVE_BUFFER_SIZE);
    int size = client->recv(buffer, RECEIVE_BUFFER_SIZE);
    if (size > 0)
    {
        ProcessPacket(buffer, size, client);
    }
    else
    {
        LOGT(("ConnectionThreadProc. Could not receive data\n"));
    }
    client->shutdown(base::shut_both);
    client->close();
    delete client;
    free(buffer);
    return 0;
}

unsigned __stdcall SiteProcessorThreadProc(LPVOID lpParameter)
{    
    base server;
    addr_in local(addr_in::addr_loopback, (uint16_t)config_siteproccesor_port);    
    if (!server.create(base::pf_inet, base::sock_stream))
    {
        LOGT(("SiteProcessorThreadProc. Could not create socket. Error: %u\n", server.error));
        return 1;
    }
    if (!server.bind(local))
    {
        LOGT(("SiteProcessorThreadProc. Could not bind socket. Error: %u\n", server.error));
        return 1;
    }
    if (!server.listen(config_siteproccesor_max_clients_count))
    {
        LOGT(("SiteProcessorThreadProc. Could not listen socket. Error: %u\n", server.error));
        return 1;
    }

    list<HANDLE> threads;
    list<HANDLE>::iterator pIterBegin;
    HANDLE* hEvent = (HANDLE*)lpParameter;
    while (WaitForSingleObject(*hEvent, 0) != WAIT_OBJECT_0)
    {
        if (server.can_read())
        {
            addr_in client_addr;
            base client = server.accept(client_addr);
            LOGT(("SiteProcessorThreadProc. Process incoming connection\n"));
            base* pClient = new base(client.fd);
            unsigned int uiThreadID = 0;
            HANDLE hThread = NULL;
            hThread = (HANDLE)_beginthreadex(NULL, 0, &ConnectionThreadProc, pClient, 0, &uiThreadID);
            if (!hThread)
            {
                client.shutdown(base::shut_both);
                client.close();
                LOGT(("SiteProcessorThreadProc. Client connection thread creation fail\n"));
            }
            else
            {
                LOGT(("SiteProcessorThreadProc. Client connection thread created. ThreadID: %u. ThreadHandle 0x%04X\n", uiThreadID, hThread));
                threads.push_back(hThread);
            }
        }
        pIterBegin = threads.begin();
        while (pIterBegin != threads.end())
        {
            if (WaitForSingleObject(*pIterBegin, 0) == WAIT_OBJECT_0)
            {
                LOGT(("SiteProcessorThreadProc. Handle closed. ThreadHandle 0x%04X\n", *pIterBegin));
                CloseHandle(*pIterBegin);
                threads.erase(pIterBegin++);
            }
            else
            {
                pIterBegin++;
            }
        }
        Sleep(1);
    }
    server.close();
    pIterBegin = threads.begin();
    while (pIterBegin != threads.end())
    {
        if (WaitForSingleObject(*pIterBegin, INFINITE) == WAIT_OBJECT_0)
        {
            LOGT(("SiteProcessorThreadProc. Handle closed. ThreadHandle 0x%04X\n", *pIterBegin));
            CloseHandle(*pIterBegin);
            threads.erase(pIterBegin++);
        }
        else
        {
            pIterBegin++;
        }
    }
    LOGT(("SiteProcessorThreadProc. Execution completed\n"));
    return 0;
}

SiteProcessorTask::SiteProcessorTask(void)
{
    hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
}

SiteProcessorTask::~SiteProcessorTask(void)
{
    CloseHandle(hEvent);
}

void SiteProcessorTask::InitTask()
{
    uiThreadID = 0;
    hThread = (HANDLE)_beginthreadex(NULL, 0, &SiteProcessorThreadProc, &hEvent, CREATE_SUSPENDED, &uiThreadID);
    if (!hThread)
        LOGT(("SiteProcessorTask::InitTask. Thread creation fail\n"));
    else
        LOGT(("SiteProcessorTask::InitTask. Thread created. ThreadID: %u. ThreadHandle 0x%04X\n", uiThreadID, hThread));
}

void SiteProcessorTask::StartTask()
{
    if (ResumeThread(hThread) == (DWORD)-1)
    {
        LOGT(("SiteProcessorTask::StartTask. Thread not started. ThreadID: %u. ThreadHandle 0x%04X\n", uiThreadID, hThread));
    }
    else
    {
        LOGT(("SiteProcessorTask::StartTask. Thread started. ThreadID: %u. ThreadHandle 0x%04X\n", uiThreadID, hThread));
    }
}

void SiteProcessorTask::StopTask()
{
    SetEvent(hEvent);
    LOGT(("SiteProcessorTask::StopTask. Send signal to thread for stopping\n"));
}

void SiteProcessorTask::WaitForStop()
{
    if (WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0)
    {
        LOGT(("SiteProcessorTask::WaitForStop. Handle closed. ThreadID: %u. ThreadHandle 0x%04X\n", uiThreadID, hThread));
        CloseHandle(hThread);
    }
}